package me.ivps.android.weibo.support.gallery;

import me.ivps.android.weibo.R;
import me.ivps.android.weibo.support.imageutility.ImageUtility;
import me.ivps.android.weibo.support.lib.AnimationRect;
import me.ivps.android.weibo.support.lib.MyAsyncTask;
import me.ivps.android.weibo.support.settinghelper.SettingUtility;
import me.ivps.android.weibo.support.utils.AnimationUtility;
import me.ivps.android.weibo.support.utils.Utility;
import uk.co.senab.photoview.PhotoView;
import uk.co.senab.photoview.PhotoViewAttacher;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateDecelerateInterpolator;

/**
 * 通用图片 Fragment
 * 
 * User: qii Date: 14-4-30
 */
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class GeneralPictureFragment extends Fragment {
    
    private static final int NAVIGATION_BAR_HEIGHT_DP_UNIT = 48;
    
    private static final int IMAGEVIEW_SOFT_LAYER_MAX_WIDTH = 2000;
    
    private static final int IMAGEVIEW_SOFT_LAYER_MAX_HEIGHT = 3000;
    
    private PhotoView photoView;
    
    private static final int ANIMATION_DURATION = 300;
    
    public static GeneralPictureFragment newInstance(String path,
            AnimationRect rect, boolean animationIn) {
        GeneralPictureFragment fragment = new GeneralPictureFragment();
        Bundle bundle = new Bundle();
        bundle.putString("path", path);
        bundle.putParcelable("rect", rect);
        bundle.putBoolean("animationIn", animationIn);
        fragment.setArguments(bundle);
        return fragment;
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.gallery_general_layout,
                container, false);
        
        photoView = (PhotoView) view.findViewById(R.id.animation);
        
        if (SettingUtility.allowClickToCloseGallery()) {
            
            photoView
                    .setOnViewTapListener(new PhotoViewAttacher.OnViewTapListener() {
                        @Override
                        public void onViewTap(View view, float x, float y) {
                            getActivity().onBackPressed();
                        }
                    });
        }
        
        LongClickListener longClickListener = ((ContainerFragment) getParentFragment())
                .getLongClickListener();
        photoView.setOnLongClickListener(longClickListener);
        
        final String path = getArguments().getString("path");
        boolean animateIn = getArguments().getBoolean("animationIn");
        final AnimationRect rect = getArguments().getParcelable("rect");
        
        if (!animateIn) {
            
            new MyAsyncTask<Void, Bitmap, Bitmap>() {
                
                @Override
                protected Bitmap doInBackground(Void... params) {
                    Bitmap bitmap = ImageUtility.decodeBitmapFromSDCard(path,
                            IMAGEVIEW_SOFT_LAYER_MAX_WIDTH,
                            IMAGEVIEW_SOFT_LAYER_MAX_HEIGHT);
                    return bitmap;
                }
                
                @Override
                protected void onPostExecute(Bitmap bitmap) {
                    super.onPostExecute(bitmap);
                    photoView.setImageBitmap(bitmap);
                }
                
            }.executeOnExecutor(MyAsyncTask.THREAD_POOL_EXECUTOR);
            
            return view;
        }
        
        final Bitmap bitmap = ImageUtility
                .decodeBitmapFromSDCard(path, IMAGEVIEW_SOFT_LAYER_MAX_WIDTH,
                        IMAGEVIEW_SOFT_LAYER_MAX_HEIGHT);
        
        photoView.setImageBitmap(bitmap);
        
        final Runnable endAction = new Runnable() {
            @Override
            public void run() {
                Bundle bundle = getArguments();
                bundle.putBoolean("animationIn", false);
            }
        };
        
        photoView.getViewTreeObserver().addOnPreDrawListener(
                new ViewTreeObserver.OnPreDrawListener() {
                    @Override
                    public boolean onPreDraw() {
                        
                        if (rect == null) {
                            photoView.getViewTreeObserver()
                                    .removeOnPreDrawListener(this);
                            return true;
                        }
                        
                        final Rect startBounds = new Rect(rect.scaledBitmapRect);
                        final Rect finalBounds = AnimationUtility
                                .getBitmapRectFromImageView(photoView);
                        
                        if (finalBounds == null) {
                            photoView.getViewTreeObserver()
                                    .removeOnPreDrawListener(this);
                            return true;
                        }
                        
                        float startScale = (float) finalBounds.width()
                                / startBounds.width();
                        
                        if (startScale * startBounds.height() > finalBounds
                                .height()) {
                            startScale = (float) finalBounds.height()
                                    / startBounds.height();
                        }
                        
                        int oriBitmapScaledWidth = (int) (finalBounds.width() / startScale);
                        int oriBitmapScaledHeight = (int) (finalBounds.height() / startScale);
                        
                        int thumbnailAndOriDeltaRightSize = Math
                                .abs(rect.scaledBitmapRect.width()
                                        - oriBitmapScaledWidth);
                        int thumbnailAndOriDeltaBottomSize = Math
                                .abs(rect.scaledBitmapRect.height()
                                        - oriBitmapScaledHeight);
                        
                        float thumbnailAndOriDeltaWidth = (float) thumbnailAndOriDeltaRightSize
                                / (float) oriBitmapScaledWidth;
                        float thumbnailAndOriDeltaHeight = (float) thumbnailAndOriDeltaBottomSize
                                / (float) oriBitmapScaledHeight;
                        
                        int deltaTop = startBounds.top - finalBounds.top;
                        int deltaLeft = startBounds.left - finalBounds.left;
                        
                        photoView.setPivotY((photoView.getHeight() - finalBounds
                                .height()) / 2);
                        photoView.setPivotX((photoView.getWidth() - finalBounds
                                .width()) / 2);
                        
                        photoView.setScaleX(1 / startScale);
                        photoView.setScaleY(1 / startScale);
                        
                        photoView.setTranslationX(deltaLeft);
                        photoView.setTranslationY(deltaTop);
                        
                        photoView
                                .animate()
                                .translationY(0)
                                .translationX(0)
                                .scaleY(1)
                                .scaleX(1)
                                .setDuration(ANIMATION_DURATION)
                                .setInterpolator(
                                        new AccelerateDecelerateInterpolator())
                                .withEndAction(endAction);
                        
                        if (rect.type == AnimationRect.TYPE_EXTEND_V
                                || rect.type == AnimationRect.TYPE_EXTEND_H) {
                            
                            AnimatorSet animationSet = new AnimatorSet();
                            animationSet.setDuration(ANIMATION_DURATION);
                            animationSet
                                    .setInterpolator(new AccelerateDecelerateInterpolator());
                            
                            animationSet.playTogether(ObjectAnimator.ofFloat(
                                    photoView, "clipBottom",
                                    thumbnailAndOriDeltaHeight, 0));
                            animationSet.start();
                            
                        }
                        else {
                            
                            AnimatorSet animationSet = new AnimatorSet();
                            animationSet.setDuration(ANIMATION_DURATION);
                            animationSet
                                    .setInterpolator(new AccelerateDecelerateInterpolator());
                            
                            float clipRectH = ((oriBitmapScaledWidth
                                    - oriBitmapScaledWidth
                                    * thumbnailAndOriDeltaWidth - rect.widgetWidth) / 2)
                                    / oriBitmapScaledWidth;
                            float clipRectV = ((oriBitmapScaledHeight
                                    - oriBitmapScaledHeight
                                    * thumbnailAndOriDeltaHeight - rect.widgetHeight) / 2)
                                    / oriBitmapScaledHeight;
                            
                            animationSet.playTogether(ObjectAnimator.ofFloat(
                                    photoView, "clipHorizontal", clipRectH, 0));
                            animationSet.playTogether(ObjectAnimator.ofFloat(
                                    photoView, "clipVertical", clipRectV, 0));
                            
                            animationSet.playTogether(ObjectAnimator.ofFloat(
                                    photoView, "clipBottom",
                                    thumbnailAndOriDeltaHeight, 0));
                            animationSet.playTogether(ObjectAnimator.ofFloat(
                                    photoView, "clipRight",
                                    thumbnailAndOriDeltaWidth, 0));
                            
                            animationSet.start();
                            
                        }
                        
                        photoView.getViewTreeObserver()
                                .removeOnPreDrawListener(this);
                        return true;
                    }
                });
        
        return view;
    }
    
    public void animationExit(ObjectAnimator backgroundAnimator) {
        
        if (Math.abs(photoView.getScale() - 1.0f) > 0.1f) {
            photoView.setScale(1, true);
            return;
        }
        
        getActivity().overridePendingTransition(0, 0);
        animateClose(backgroundAnimator);
        
    }
    
    private void animateClose(ObjectAnimator backgroundAnimator) {
        
        AnimationRect rect = getArguments().getParcelable("rect");
        
        if (rect == null) {
            photoView.animate().alpha(0);
            backgroundAnimator.start();
            return;
        }
        
        final Rect startBounds = rect.scaledBitmapRect;
        final Rect finalBounds = AnimationUtility
                .getBitmapRectFromImageView(photoView);
        
        if (finalBounds == null) {
            photoView.animate().alpha(0);
            backgroundAnimator.start();
            return;
        }
        
        if (Utility.isDevicePort() != rect.isScreenPortrait) {
            photoView.animate().alpha(0);
            backgroundAnimator.start();
            return;
        }
        
        float startScale;
        if ((float) finalBounds.width() / finalBounds.height() > (float) startBounds
                .width() / startBounds.height()) {
            startScale = (float) startBounds.height() / finalBounds.height();
            
        }
        else {
            startScale = (float) startBounds.width() / finalBounds.width();
        }
        
        final float startScaleFinal = startScale;
        
        int oriBitmapScaledWidth = (int) (finalBounds.width() * startScale);
        int oriBitmapScaledHeight = (int) (finalBounds.height() * startScale);
        
        // sina server may cut thumbnail's right or bottom
        int thumbnailAndOriDeltaRightSize = Math.abs(rect.scaledBitmapRect
                .width() - oriBitmapScaledWidth);
        int thumbnailAndOriDeltaBottomSize = Math.abs(rect.scaledBitmapRect
                .height() - oriBitmapScaledHeight);
        
        float serverClipThumbnailRightSizePercent = (float) thumbnailAndOriDeltaRightSize
                / (float) oriBitmapScaledWidth;
        float serverClipThumbnailBottomSizePercent = (float) thumbnailAndOriDeltaBottomSize
                / (float) oriBitmapScaledHeight;
        
        int deltaTop = startBounds.top - finalBounds.top;
        int deltaLeft = startBounds.left - finalBounds.left;
        
        photoView.setPivotY((photoView.getHeight() - finalBounds.height()) / 2);
        photoView.setPivotX((photoView.getWidth() - finalBounds.width()) / 2);
        
        photoView.animate().translationX(deltaLeft).translationY(deltaTop)
                .scaleY(startScaleFinal).scaleX(startScaleFinal)
                .setDuration(ANIMATION_DURATION)
                .setInterpolator(new AccelerateDecelerateInterpolator())
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        
                        photoView.animate().alpha(0.0f).setDuration(200)
                                .withEndAction(new Runnable() {
                                    @Override
                                    public void run() {
                                        
                                    }
                                });
                        
                    }
                });
        
        if (rect.type == AnimationRect.TYPE_EXTEND_V
                || rect.type == AnimationRect.TYPE_EXTEND_H) {
            AnimatorSet animationSet = new AnimatorSet();
            animationSet.setDuration(ANIMATION_DURATION);
            animationSet
                    .setInterpolator(new AccelerateDecelerateInterpolator());
            
            animationSet.playTogether(backgroundAnimator);
            animationSet.playTogether(ObjectAnimator.ofFloat(photoView,
                    "clipBottom", 0, serverClipThumbnailBottomSizePercent));
            animationSet.start();
        }
        else {
            
            AnimatorSet animationSet = new AnimatorSet();
            animationSet.setDuration(ANIMATION_DURATION);
            animationSet
                    .setInterpolator(new AccelerateDecelerateInterpolator());
            
            animationSet.playTogether(backgroundAnimator);
            
            float clipRectH = ((oriBitmapScaledWidth - oriBitmapScaledWidth
                    * serverClipThumbnailRightSizePercent - rect.widgetWidth) / 2)
                    / oriBitmapScaledWidth;
            float clipRectV = ((oriBitmapScaledHeight - oriBitmapScaledHeight
                    * serverClipThumbnailBottomSizePercent - rect.widgetHeight) / 2)
                    / oriBitmapScaledHeight;
            
            animationSet.playTogether(ObjectAnimator.ofFloat(photoView,
                    "clipHorizontal", 0, clipRectH));
            animationSet.playTogether(ObjectAnimator.ofFloat(photoView,
                    "clipVertical", 0, clipRectV));
            
            animationSet.playTogether(ObjectAnimator.ofFloat(photoView,
                    "clipBottom", 0, serverClipThumbnailBottomSizePercent));
            animationSet.playTogether(ObjectAnimator.ofFloat(photoView,
                    "clipRight", 0, serverClipThumbnailRightSizePercent));
            
            animationSet.start();
            
        }
    }
    
}
